{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/lib/python3.6/dist-packages/tensorflow/python/util/tf_inspect.py:75: DeprecationWarning: inspect.getargspec() is deprecated since Python 3.0, use inspect.signature() or inspect.getfullargspec()\n",
      "  return _inspect.getargspec(target)\n",
      "/usr/local/lib/python3.6/dist-packages/tensorflow/python/util/tf_inspect.py:75: DeprecationWarning: inspect.getargspec() is deprecated since Python 3.0, use inspect.signature() or inspect.getfullargspec()\n",
      "  return _inspect.getargspec(target)\n",
      "/usr/local/lib/python3.6/dist-packages/tensorflow/python/util/tf_inspect.py:75: DeprecationWarning: inspect.getargspec() is deprecated since Python 3.0, use inspect.signature() or inspect.getfullargspec()\n",
      "  return _inspect.getargspec(target)\n",
      "/usr/local/lib/python3.6/dist-packages/tensorflow/python/util/tf_inspect.py:75: DeprecationWarning: inspect.getargspec() is deprecated since Python 3.0, use inspect.signature() or inspect.getfullargspec()\n",
      "  return _inspect.getargspec(target)\n",
      "/usr/local/lib/python3.6/dist-packages/tensorflow/python/util/tf_inspect.py:75: DeprecationWarning: inspect.getargspec() is deprecated since Python 3.0, use inspect.signature() or inspect.getfullargspec()\n",
      "  return _inspect.getargspec(target)\n",
      "/usr/local/lib/python3.6/dist-packages/tensorflow/python/util/tf_inspect.py:75: DeprecationWarning: inspect.getargspec() is deprecated since Python 3.0, use inspect.signature() or inspect.getfullargspec()\n",
      "  return _inspect.getargspec(target)\n",
      "/usr/local/lib/python3.6/dist-packages/tensorflow/python/util/tf_inspect.py:75: DeprecationWarning: inspect.getargspec() is deprecated since Python 3.0, use inspect.signature() or inspect.getfullargspec()\n",
      "  return _inspect.getargspec(target)\n",
      "/usr/local/lib/python3.6/dist-packages/tensorflow/python/util/tf_inspect.py:75: DeprecationWarning: inspect.getargspec() is deprecated since Python 3.0, use inspect.signature() or inspect.getfullargspec()\n",
      "  return _inspect.getargspec(target)\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "import random\n",
    "import time\n",
    "import collections\n",
    "from tqdm import tqdm\n",
    "from tensor2tensor.utils import beam_search\n",
    "sns.set()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "with open('shakespeare.txt') as fopen:\n",
    "    shakespeare = fopen.read()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "char2idx = {c: i+3 for i, c in enumerate(set(shakespeare))}\n",
    "char2idx['<pad>'] = 0\n",
    "char2idx['<start>'] = 1\n",
    "char2idx['<end>'] = 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "idx2char = {v:k for k, v in char2idx.items()}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "batch_size = 32\n",
    "sequence_length = 100\n",
    "step = 25"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1115394"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X = [char2idx[char] for char in list(shakespeare)]\n",
    "len(X)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(44612, 100)"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len_win = sequence_length\n",
    "sequences = []\n",
    "for i in range(0, len(X) - len_win, step):\n",
    "    clip = X[i: i+len_win]\n",
    "    sequences.append(clip)\n",
    "sequences = np.array(sequences)\n",
    "sequences.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "def start_sent(x):\n",
    "    _x = tf.fill([tf.shape(x)[0], 1], char2idx['<start>']) \n",
    "    return tf.concat([_x, x], 1)\n",
    "\n",
    "def end_sent(x):\n",
    "    _x = tf.fill([tf.shape(x)[0], 1], char2idx['<end>']) \n",
    "    return tf.concat([x, _x], 1)\n",
    "\n",
    "def positional_embedding(pos_seq, inv_freq, bsz = None):\n",
    "    sinusoid_inp = tf.einsum('i,j->ij', pos_seq, inv_freq)\n",
    "    pos_emb = tf.concat([tf.sin(sinusoid_inp), tf.cos(sinusoid_inp)], -1)\n",
    "    if bsz is not None:\n",
    "        return tf.tile(pos_emb[:, None, :], [1, bsz, 1])\n",
    "    else:\n",
    "        return pos_emb[:, None, :]\n",
    "\n",
    "\n",
    "def positionwise_FF(inp, d_model, d_inner, kernel_initializer, scope = 'ff'):\n",
    "    output = inp\n",
    "    with tf.variable_scope(scope):\n",
    "        output = tf.layers.dense(\n",
    "            inp,\n",
    "            d_inner,\n",
    "            activation = tf.nn.relu,\n",
    "            kernel_initializer = kernel_initializer,\n",
    "            name = 'layer_1',\n",
    "        )\n",
    "        output = tf.layers.dense(\n",
    "            output,\n",
    "            d_model,\n",
    "            kernel_initializer = kernel_initializer,\n",
    "            name = 'layer_2',\n",
    "        )\n",
    "        output = tf.contrib.layers.layer_norm(\n",
    "            output + inp, begin_norm_axis = -1\n",
    "        )\n",
    "    return output\n",
    "\n",
    "def rel_shift(x):\n",
    "    x_size = tf.shape(x)\n",
    "\n",
    "    x = tf.pad(x, [[0, 0], [1, 0], [0, 0], [0, 0]])\n",
    "    x = tf.reshape(x, [x_size[1] + 1, x_size[0], x_size[2], x_size[3]])\n",
    "    x = tf.slice(x, [1, 0, 0, 0], [-1, -1, -1, -1])\n",
    "    x = tf.reshape(x, x_size)\n",
    "\n",
    "    return x\n",
    "\n",
    "\n",
    "def rel_multihead_attn(\n",
    "    w,\n",
    "    r,\n",
    "    r_w_bias,\n",
    "    r_r_bias,\n",
    "    attn_mask,\n",
    "    mems,\n",
    "    d_model,\n",
    "    n_head,\n",
    "    d_head,\n",
    "    kernel_initializer,\n",
    "    scope = 'rel_attn',\n",
    "):\n",
    "    scale = 1 / (d_head ** 0.5)\n",
    "    with tf.variable_scope(scope):\n",
    "        qlen = tf.shape(w)[0]\n",
    "        rlen = tf.shape(r)[0]\n",
    "        bsz = tf.shape(w)[1]\n",
    "\n",
    "        cat = (\n",
    "            tf.concat([mems, w], 0)\n",
    "            if mems is not None and mems.shape.ndims > 1\n",
    "            else w\n",
    "        )\n",
    "        w_heads = tf.layers.dense(\n",
    "            cat,\n",
    "            3 * n_head * d_head,\n",
    "            use_bias = False,\n",
    "            kernel_initializer = kernel_initializer,\n",
    "            name = 'qkv',\n",
    "        )\n",
    "        r_head_k = tf.layers.dense(\n",
    "            r,\n",
    "            n_head * d_head,\n",
    "            use_bias = False,\n",
    "            kernel_initializer = kernel_initializer,\n",
    "            name = 'r',\n",
    "        )\n",
    "\n",
    "        w_head_q, w_head_k, w_head_v = tf.split(w_heads, 3, -1)\n",
    "        w_head_q = w_head_q[-qlen:]\n",
    "\n",
    "        klen = tf.shape(w_head_k)[0]\n",
    "\n",
    "        w_head_q = tf.reshape(w_head_q, [qlen, bsz, n_head, d_head])\n",
    "        w_head_k = tf.reshape(w_head_k, [klen, bsz, n_head, d_head])\n",
    "        w_head_v = tf.reshape(w_head_v, [klen, bsz, n_head, d_head])\n",
    "\n",
    "        r_head_k = tf.reshape(r_head_k, [rlen, n_head, d_head])\n",
    "        rw_head_q = w_head_q + r_w_bias\n",
    "        rr_head_q = w_head_q + r_r_bias\n",
    "\n",
    "        AC = tf.einsum('ibnd,jbnd->ijbn', rw_head_q, w_head_k)\n",
    "        BD = tf.einsum('ibnd,jnd->ijbn', rr_head_q, r_head_k)\n",
    "        BD = rel_shift(BD)\n",
    "        \n",
    "        paddings = tf.fill(tf.shape(BD), float('-inf'))\n",
    "\n",
    "        attn_score = (AC + BD) * scale\n",
    "        attn_mask_t = attn_mask[:, :, None, None]\n",
    "        attn_score = attn_score * (1 - attn_mask_t) - 1e30 * attn_mask_t\n",
    "\n",
    "        attn_prob = tf.nn.softmax(attn_score, 1)\n",
    "        attn_vec = tf.einsum('ijbn,jbnd->ibnd', attn_prob, w_head_v)\n",
    "        size_t = tf.shape(attn_vec)\n",
    "        attn_vec = tf.reshape(attn_vec, [size_t[0], size_t[1], n_head * d_head])\n",
    "\n",
    "        attn_out = tf.layers.dense(\n",
    "            attn_vec,\n",
    "            d_model,\n",
    "            use_bias = False,\n",
    "            kernel_initializer = kernel_initializer,\n",
    "            name = 'o',\n",
    "        )\n",
    "\n",
    "        output = tf.contrib.layers.layer_norm(\n",
    "            attn_out + w, begin_norm_axis = -1\n",
    "        )\n",
    "    return output\n",
    "\n",
    "def embedding_lookup(lookup_table, x):\n",
    "    return tf.nn.embedding_lookup(lookup_table, x)\n",
    "\n",
    "\n",
    "def mask_adaptive_embedding_lookup(\n",
    "    x,\n",
    "    n_token,\n",
    "    d_embed,\n",
    "    d_proj,\n",
    "    cutoffs,\n",
    "    initializer,\n",
    "    proj_initializer,\n",
    "    div_val = 1,\n",
    "    proj_same_dim = True,\n",
    "    scope = 'adaptive_embed',\n",
    "    **kwargs\n",
    "):\n",
    "    emb_scale = d_proj ** 0.5\n",
    "    with tf.variable_scope(scope):\n",
    "        if div_val == 1:\n",
    "            lookup_table = tf.get_variable(\n",
    "                'lookup_table', [n_token, d_embed], initializer = initializer\n",
    "            )\n",
    "            y = embedding_lookup(lookup_table, x)\n",
    "            if d_proj != d_embed:\n",
    "                proj_W = tf.get_variable(\n",
    "                    'proj_W', [d_embed, d_proj], initializer = proj_initializer\n",
    "                )\n",
    "                y = tf.einsum('ibe,ed->ibd', y, proj_W)\n",
    "            else:\n",
    "                proj_W = None\n",
    "            ret_params = [lookup_table, proj_W]\n",
    "        else:\n",
    "            tables, projs = [], []\n",
    "            cutoff_ends = [0] + cutoffs + [n_token]\n",
    "            x_size = tf.shape(x)\n",
    "            y = tf.zeros([x_size[0], x_size[1], d_proj])\n",
    "            for i in range(len(cutoff_ends) - 1):\n",
    "                with tf.variable_scope('cutoff_{}'.format(i)):\n",
    "                    l_idx, r_idx = cutoff_ends[i], cutoff_ends[i + 1]\n",
    "                    mask = (x >= l_idx) & (x < r_idx)\n",
    "                    cur_x = tf.boolean_mask(x, mask) - l_idx\n",
    "                    cur_d_embed = d_embed // (div_val ** i)\n",
    "                    lookup_table = tf.get_variable(\n",
    "                        'lookup_table',\n",
    "                        [r_idx - l_idx, cur_d_embed],\n",
    "                        initializer = initializer,\n",
    "                    )\n",
    "                    cur_y = embedding_lookup(lookup_table, cur_x)\n",
    "                    if d_proj == cur_d_embed and not proj_same_dim:\n",
    "                        proj_W = None\n",
    "                    else:\n",
    "                        proj_W = tf.get_variable(\n",
    "                            'proj_W',\n",
    "                            [cur_d_embed, d_proj],\n",
    "                            initializer = proj_initializer,\n",
    "                        )\n",
    "                        cur_y = tf.einsum('id,de->ie', cur_y, proj_W)\n",
    "                    mask_idx = tf.to_int64(tf.where(mask))\n",
    "                    y += tf.scatter_nd(\n",
    "                        mask_idx, cur_y, tf.to_int64(tf.shape(y))\n",
    "                    )\n",
    "                    tables.append(lookup_table)\n",
    "                    projs.append(proj_W)\n",
    "            ret_params = [tables, projs]\n",
    "\n",
    "    y *= emb_scale\n",
    "    return y, ret_params\n",
    "\n",
    "\n",
    "def _create_mask(qlen, mlen, same_length = False):\n",
    "    attn_mask = tf.ones([qlen, qlen])\n",
    "    mask_u = tf.matrix_band_part(attn_mask, 0, -1)\n",
    "    mask_dia = tf.matrix_band_part(attn_mask, 0, 0)\n",
    "    attn_mask_pad = tf.zeros([qlen, mlen])\n",
    "    ret = tf.concat([attn_mask_pad, mask_u - mask_dia], 1)\n",
    "    if same_length:\n",
    "        mask_l = tf.matrix_band_part(attn_mask, -1, 0)\n",
    "        ret = tf.concat([ret[:, :qlen] + mask_l - mask_dia, ret[:, qlen:]], 1)\n",
    "    return ret\n",
    "\n",
    "\n",
    "def _cache_mem(curr_out, prev_mem, mem_len = None):\n",
    "    if mem_len is None or prev_mem is None:\n",
    "        new_mem = curr_out\n",
    "    elif mem_len == 0:\n",
    "        return prev_mem\n",
    "    else:\n",
    "        new_mem = tf.concat([prev_mem, curr_out], 0)[-mem_len:]\n",
    "\n",
    "    return tf.stop_gradient(new_mem)\n",
    "\n",
    "def transformer(\n",
    "    dec_inp,\n",
    "    mems,\n",
    "    n_token,\n",
    "    n_layer,\n",
    "    d_model,\n",
    "    d_embed,\n",
    "    n_head,\n",
    "    d_head,\n",
    "    d_inner,\n",
    "    initializer,\n",
    "    proj_initializer = None,\n",
    "    mem_len = None,\n",
    "    cutoffs = [],\n",
    "    div_val = 1,\n",
    "    tie_projs = [],\n",
    "    same_length = False,\n",
    "    clamp_len = -1,\n",
    "    untie_r = False,\n",
    "    proj_same_dim = True,\n",
    "    scope = 'transformer',\n",
    "    reuse = tf.AUTO_REUSE\n",
    "):\n",
    "    \"\"\"\n",
    "  cutoffs: a list of python int. Cutoffs for adaptive softmax.\n",
    "  tie_projs: a list of python bools. Whether to tie the projections.\n",
    "  perms: a list of tensors. Each tensor should of size [len, bsz, bin_size].\n",
    "        Only used in the adaptive setting.\n",
    "  \"\"\"\n",
    "    new_mems = []\n",
    "    with tf.variable_scope(scope,reuse=reuse):\n",
    "        if untie_r:\n",
    "            r_w_bias = tf.get_variable(\n",
    "                'r_w_bias', [n_layer, n_head, d_head], initializer = initializer\n",
    "            )\n",
    "            r_r_bias = tf.get_variable(\n",
    "                'r_r_bias', [n_layer, n_head, d_head], initializer = initializer\n",
    "            )\n",
    "        else:\n",
    "            r_w_bias = tf.get_variable(\n",
    "                'r_w_bias', [n_head, d_head], initializer = initializer\n",
    "            )\n",
    "            r_r_bias = tf.get_variable(\n",
    "                'r_r_bias', [n_head, d_head], initializer = initializer\n",
    "            )\n",
    "\n",
    "        qlen = tf.shape(dec_inp)[0]\n",
    "        mlen = tf.shape(mems[0])[0] if mems is not None else 0\n",
    "        klen = mlen + qlen\n",
    "\n",
    "        if proj_initializer is None:\n",
    "            proj_initializer = initializer\n",
    "        lookup_fn = mask_adaptive_embedding_lookup\n",
    "        embeddings, shared_params = lookup_fn(\n",
    "            x = dec_inp,\n",
    "            n_token = n_token,\n",
    "            d_embed = d_embed,\n",
    "            d_proj = d_model,\n",
    "            cutoffs = cutoffs,\n",
    "            initializer = initializer,\n",
    "            proj_initializer = proj_initializer,\n",
    "            div_val = div_val,\n",
    "            proj_same_dim = proj_same_dim,\n",
    "        )\n",
    "        attn_mask = _create_mask(qlen, mlen, same_length)\n",
    "\n",
    "        pos_seq = tf.range(klen - 1, -1, -1.0)\n",
    "        if clamp_len > 0:\n",
    "            pos_seq = tf.minimum(pos_seq, clamp_len)\n",
    "        inv_freq = 1 / (10000 ** (tf.range(0, d_model, 2.0) / d_model))\n",
    "        pos_emb = positional_embedding(pos_seq, inv_freq)\n",
    "\n",
    "        if mems is None:\n",
    "            mems = [None] * n_layer\n",
    "        output = embeddings\n",
    "        for i in range(n_layer):\n",
    "            # cache new mems\n",
    "            new_mems.append(_cache_mem(output, mems[i], mem_len))\n",
    "\n",
    "            with tf.variable_scope('layer_{}'.format(i)):\n",
    "                output = rel_multihead_attn(\n",
    "                    w = output,\n",
    "                    r = pos_emb,\n",
    "                    r_w_bias = r_w_bias if not untie_r else r_w_bias[i],\n",
    "                    r_r_bias = r_r_bias if not untie_r else r_r_bias[i],\n",
    "                    attn_mask = attn_mask,\n",
    "                    mems = mems[i],\n",
    "                    d_model = d_model,\n",
    "                    n_head = n_head,\n",
    "                    d_head = d_head,\n",
    "                    kernel_initializer = initializer,\n",
    "                )\n",
    "                output = positionwise_FF(\n",
    "                    inp = output,\n",
    "                    d_model = d_model,\n",
    "                    d_inner = d_inner,\n",
    "                    kernel_initializer = initializer,\n",
    "                )\n",
    "        return output, new_mems\n",
    "    \n",
    "class Generator:\n",
    "    def __init__(self, size_layer, num_layers, embedded_size,\n",
    "                 dict_size, learning_rate, kernel_size = 5):\n",
    "        \n",
    "        self.X = tf.placeholder(tf.int32, [None, None])\n",
    "        self.Y = tf.placeholder(tf.int32, [None, None])\n",
    "        self.X_seq_len = tf.count_nonzero(self.X, 1, dtype=tf.int32)\n",
    "        self.Y_seq_len = tf.count_nonzero(self.Y, 1, dtype=tf.int32)\n",
    "        self.dict_size = dict_size\n",
    "        self.embedded_size = embedded_size\n",
    "        self.size_layer = size_layer\n",
    "        self.kernel_size = kernel_size\n",
    "        self.num_layers = num_layers\n",
    "        batch_size = tf.shape(self.X)[0]\n",
    "        x = start_sent(self.X)\n",
    "        y = end_sent(self.Y)\n",
    "        self.y = y\n",
    "        self.x = x\n",
    "                \n",
    "        logits = self.forward(x)\n",
    "        self.logits = logits\n",
    "        \n",
    "        self.cost = tf.reduce_mean(tf.contrib.seq2seq.sequence_loss(\n",
    "            logits = logits,\n",
    "            targets = y,\n",
    "            weights = tf.to_float(tf.ones_like(y))))\n",
    "        self.optimizer = tf.train.AdamOptimizer(learning_rate).minimize(self.cost)\n",
    "        \n",
    "        masks = tf.sequence_mask(self.Y_seq_len, tf.reduce_max(self.Y_seq_len), dtype=tf.float32)\n",
    "        y_t = tf.argmax(logits,axis=2)\n",
    "        y_t = tf.cast(y_t, tf.int32)\n",
    "        self.prediction = tf.boolean_mask(y_t, masks)\n",
    "        mask_label = tf.boolean_mask(y, masks)\n",
    "        correct_pred = tf.equal(self.prediction, mask_label)\n",
    "        correct_index = tf.cast(correct_pred, tf.float32)\n",
    "        self.accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))\n",
    "        \n",
    "    def forward(self, x, reuse = False):\n",
    "        \n",
    "        with tf.variable_scope('embed', reuse=reuse):\n",
    "            initializer = tf.initializers.random_normal(stddev = 0.1)\n",
    "            memory = tf.fill(\n",
    "                [self.num_layers, tf.shape(x)[0], tf.shape(x)[1], self.embedded_size], char2idx['<pad>']\n",
    "            )\n",
    "            memory = tf.cast(memory, tf.float32)\n",
    "            logits, next_memory = transformer(\n",
    "                x,\n",
    "                memory,\n",
    "                self.dict_size,\n",
    "                self.num_layers,\n",
    "                self.embedded_size,\n",
    "                self.embedded_size,\n",
    "                self.kernel_size,\n",
    "                self.kernel_size,\n",
    "                self.embedded_size * 2,\n",
    "                initializer,\n",
    "                scope='1'\n",
    "            )\n",
    "            logits, next_memory = transformer(\n",
    "                x,\n",
    "                next_memory,\n",
    "                self.dict_size,\n",
    "                self.num_layers,\n",
    "                self.embedded_size,\n",
    "                self.embedded_size,\n",
    "                self.kernel_size,\n",
    "                self.kernel_size,\n",
    "                self.embedded_size * 2,\n",
    "                initializer,\n",
    "                scope='2'\n",
    "            )\n",
    "            logits, next_memory = transformer(\n",
    "                x,\n",
    "                next_memory,\n",
    "                self.dict_size,\n",
    "                self.num_layers,\n",
    "                self.embedded_size,\n",
    "                self.embedded_size,\n",
    "                self.kernel_size,\n",
    "                self.kernel_size,\n",
    "                self.embedded_size * 2,\n",
    "                initializer,\n",
    "                scope='3'\n",
    "            )\n",
    "        with tf.variable_scope('logits', reuse=reuse):\n",
    "            return tf.layers.dense(logits, self.dict_size)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "def beam_search_decoding(length = 1000):\n",
    "    initial_ids = tf.constant(char2idx['<start>'], tf.int32, [1])\n",
    "\n",
    "    def symbols_to_logits(ids):\n",
    "        logits = model.forward(ids, reuse = True)\n",
    "        return logits[:, tf.shape(ids)[1]-1, :]\n",
    "\n",
    "    final_ids, final_probs, _ = beam_search.beam_search(\n",
    "        symbols_to_logits,\n",
    "        initial_ids,\n",
    "        5,\n",
    "        length,\n",
    "        len(char2idx),\n",
    "        0.0,\n",
    "        eos_id = char2idx['<end>'])\n",
    "    \n",
    "    return final_ids[0, 0, :]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "learning_rate = 0.001\n",
    "epoch = 10\n",
    "num_layers = 4\n",
    "size_layer = 128\n",
    "possible_batch_id = range(len(X) - sequence_length - 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/lib/python3.6/dist-packages/numpy/lib/type_check.py:546: DeprecationWarning: np.asscalar(a) is deprecated since NumPy v1.16, use a.item() instead\n",
      "  'a.item() instead', DeprecationWarning, stacklevel=1)\n"
     ]
    }
   ],
   "source": [
    "tf.reset_default_graph()\n",
    "sess = tf.InteractiveSession()\n",
    "model = Generator(size_layer, num_layers, size_layer, len(char2idx), learning_rate)\n",
    "model.generate = beam_search_decoding()\n",
    "sess.run(tf.global_variables_initializer())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0.013, 4.708201]"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "batch_x = sequences[:10]\n",
    "sess.run([model.accuracy, model.cost],feed_dict = {model.X: batch_x,\n",
    "                                                  model.Y: batch_x})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 1395/1395 [01:37<00:00, 15.61it/s, accuracy=0.218, cost=2.56]\n",
      "minibatch loop:   0%|          | 2/1395 [00:00<01:36, 14.51it/s, accuracy=0.251, cost=2.62]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 1, average cost 2.526423, average accuracy 0.265222\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 1395/1395 [01:36<00:00, 14.41it/s, accuracy=0.222, cost=2.55]\n",
      "minibatch loop:   0%|          | 2/1395 [00:00<01:36, 14.48it/s, accuracy=0.252, cost=2.6]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 2, average cost 2.495012, average accuracy 0.268813\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 1395/1395 [01:36<00:00, 14.45it/s, accuracy=0.215, cost=2.54]\n",
      "minibatch loop:   0%|          | 2/1395 [00:00<01:35, 14.55it/s, accuracy=0.249, cost=2.6]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 3, average cost 2.489342, average accuracy 0.269691\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 1395/1395 [01:36<00:00, 14.46it/s, accuracy=0.218, cost=2.54]\n",
      "minibatch loop:   0%|          | 2/1395 [00:00<01:35, 14.66it/s, accuracy=0.249, cost=2.59]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 4, average cost 2.486434, average accuracy 0.270104\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 1395/1395 [01:36<00:00, 14.46it/s, accuracy=0.213, cost=2.54]\n",
      "minibatch loop:   0%|          | 2/1395 [00:00<01:36, 14.39it/s, accuracy=0.249, cost=2.59]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 5, average cost 2.484412, average accuracy 0.270449\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 1395/1395 [01:36<00:00, 14.45it/s, accuracy=0.23, cost=2.54] \n",
      "minibatch loop:   0%|          | 2/1395 [00:00<01:38, 14.17it/s, accuracy=0.249, cost=2.59]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 6, average cost 2.482941, average accuracy 0.270631\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 1395/1395 [01:36<00:00, 14.42it/s, accuracy=0.228, cost=2.53]\n",
      "minibatch loop:   0%|          | 2/1395 [00:00<01:35, 14.54it/s, accuracy=0.251, cost=2.59]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 7, average cost 2.481727, average accuracy 0.270937\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 1395/1395 [01:36<00:00, 14.38it/s, accuracy=0.228, cost=2.51]\n",
      "minibatch loop:   0%|          | 2/1395 [00:00<01:36, 14.45it/s, accuracy=0.249, cost=2.59]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 8, average cost 2.480899, average accuracy 0.270923\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 1395/1395 [01:36<00:00, 14.46it/s, accuracy=0.222, cost=2.53]\n",
      "minibatch loop:   0%|          | 2/1395 [00:00<01:35, 14.59it/s, accuracy=0.24, cost=2.58]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 9, average cost 2.479794, average accuracy 0.270906\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 1395/1395 [01:36<00:00, 14.48it/s, accuracy=0.228, cost=2.53]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 10, average cost 2.479051, average accuracy 0.271049\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "LOST, ACCURACY = [], []\n",
    "for e in range(epoch):\n",
    "    pbar = tqdm(\n",
    "        range(0, len(sequences), batch_size), desc = 'minibatch loop')\n",
    "    total_cost, total_accuracy = 0, 0\n",
    "    for i in pbar:\n",
    "        batch_x = sequences[i : min(i + batch_size, len(sequences))]\n",
    "        _, accuracy, cost = sess.run([model.optimizer, model.accuracy, model.cost],\n",
    "                                     feed_dict = {model.X: batch_x,\n",
    "                                                  model.Y: batch_x})\n",
    "        total_cost += cost\n",
    "        total_accuracy += accuracy\n",
    "        pbar.set_postfix(cost = cost, accuracy = accuracy)\n",
    "        LOST.append(cost)\n",
    "        ACCURACY.append(accuracy)\n",
    "    total_cost /= (len(sequences) / batch_size)\n",
    "    total_accuracy /= (len(sequences) / batch_size)\n",
    "    print('epoch %d, average cost %f, average accuracy %f'%(e + 1, total_cost, total_accuracy))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1080x360 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize = (15, 5))\n",
    "plt.subplot(1, 2, 1)\n",
    "EPOCH = np.arange(len(LOST))\n",
    "plt.plot(EPOCH, LOST)\n",
    "plt.xlabel('epoch'); plt.ylabel('loss')\n",
    "plt.subplot(1, 2, 2)\n",
    "plt.plot(EPOCH, ACCURACY)\n",
    "plt.xlabel('epoch'); plt.ylabel('accuracy')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<start> the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the the\n"
     ]
    }
   ],
   "source": [
    "print(''.join([idx2char[i] for i in sess.run(model.generate)]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
